#include<stdio.h>
#include<unistd.h>
#include<pthread.h>

//餐厅买饭-----------条件变量实现合理化，互斥锁实现安全
//多对多的情况下
//尽可能使用多个不同的等待队列----------------唤醒合理化
//
int count=0;  //表示柜台是否有饭 
pthread_mutex_t mutex;
pthread_cond_t cond_cus;  //顾客等待队列
pthread_cond_t cond_cook;  //厨师等待队列

void* customer(void* arg)
{
  while(1){
    //首先进行加锁
    pthread_mutex_lock(&mutex);
    while(count<=0){
      //没有饭，阻塞
      pthread_cond_wait(&cond_cus,&mutex);
    }
    //count==1 有饭，进行吃饭
    printf("%p 准备吃饭------再来一碗！\n",pthread_self());
    count--;  
    pthread_cond_signal(&cond_cook); //唤醒厨师来做饭
    pthread_mutex_unlock(&mutex);
  }
  return NULL;
}

void* cook(void* arg)
{
  while(1){
    pthread_mutex_lock(&mutex);
    while(count>=1){
      //有饭，则阻塞
      pthread_cond_wait(&cond_cook,&mutex);
    }
    //count==0 没有饭
    printf("%p 厨师做饭了-----快来吃饭！\n",pthread_self());
    count++;
    pthread_cond_signal(&cond_cus);  //唤醒顾客来吃饭
    pthread_mutex_unlock(&mutex);
  }
  return NULL;
}
int main()
{
  pthread_mutex_init(&mutex,NULL);
  pthread_cond_init(&cond_cus,NULL);
  pthread_cond_init(&cond_cook,NULL);

  pthread_t cus_tid[4],cook_tid[4] ;  //创建两个线程
  int i=0;
  for(;i<4;++i){
    int ret=pthread_create(&cus_tid[i],NULL,customer,NULL);
    if(ret!=0){
      perror("pthread_create error!\n");
      return -1;
    }

    ret=pthread_create(&cook_tid[i],NULL,cook,NULL);
    if(ret!=0){
      perror("pthread_create error!\n");
      return -1;
    }
  }

  //线程等待
  for(i=0;i<4;++i){
    pthread_join(cus_tid[i],NULL);
    pthread_join(cook_tid[i],NULL);
  }
  //销毁
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&cond_cus);
  pthread_cond_destroy(&cond_cook);

  return 0;
}
